package db

import (
	"context"
	"os"

	"gitee.com/chunanyong/zorm"

	//00.引入数据库驱动
	"database/sql"
	"fmt"

	_ "gitee.com/chunanyong/dm"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"github.com/spf13/viper"
)

//dbDao 代表一个数据库,如果有多个数据库,就对应声明多个DBDao
var lawsuitDao *zorm.DBDao

// ctx默认应该有 web层传入,例如gin的c.Request.Context().这里只是模拟
var ctx = context.Background()

//01.初始化DBDao
func initDmDb() {

	//自定义zorm日志输出
	//zorm.LogCallDepth = 4 //日志调用的层级
	//zorm.FuncLogError = myFuncLogError //记录异常日志的函数
	//zorm.FuncLogPanic = myFuncLogPanic //记录panic日志,默认使用ZormErrorLog实现
	//zorm.FuncPrintSQL = myFuncPrintSQL //打印sql的函数

	//自定义日志输出格式,把FuncPrintSQL函数重新赋值
	//log.SetFlags(log.LstdFlags)
	//zorm.FuncPrintSQL = zorm.FuncPrintSQL

	//dbDaoConfig 数据库的配置.这里只是模拟,生产应该是读取配置配置文件,构造DataSourceConfig
	dbDaoConfig := zorm.DataSourceConfig{
		//DSN 数据库的连接字符串
		//DSN: "lawsuit:123456789@tcp(192.168.20.240:5236)/lawsuit?charset=utf8",
		DSN: "dm://lawsuit:123456789@192.168.20.240:5236",
		//数据库驱动名称:mysql,postgres,oci8,sqlserver,sqlite3,dm,kingbase,aci 和DBType对应,处理数据库有多个驱动
		DriverName: "dm",
		//数据库类型(方言判断依据):mysql,postgresql,oracle,mssql,sqlite,dm,kingbase,shentong 和 DriverName 对应,处理数据库有多个驱动
		DBType: "dm",
		//MaxOpenConns 数据库最大连接数 默认50
		MaxOpenConns: 50,
		//MaxIdleConns 数据库最大空闲连接数 默认50
		MaxIdleConns: 50,
		//ConnMaxLifetimeSecond 连接存活秒时间. 默认600(10分钟)后连接被销毁重建.避免数据库主动断开连接,造成死连接.MySQL默认wait_timeout 28800秒(8小时)
		ConnMaxLifetimeSecond: 600,
		//PrintSQL 打印SQL.会使用FuncPrintSQL记录SQL
		PrintSQL: true,
		//DefaultTxOptions 事务隔离级别的默认配置,默认为nil
		//DefaultTxOptions: nil,
		//DefaultTxOptions: &sql.TxOptions{Isolation: sql.LevelDefault},
	}

	// 根据dbDaoConfig创建dbDao, 一个数据库只执行一次,第一个执行的数据库为 defaultDao,后续zorm.xxx方法,默认使用的就是defaultDao
	lawsuitDao, _ = zorm.NewDBDao(&dbDaoConfig)
}

func initSysBaseDb() {

	//自定义zorm日志输出
	//zorm.LogCallDepth = 4 //日志调用的层级
	//zorm.FuncLogError = myFuncLogError //记录异常日志的函数
	//zorm.FuncLogPanic = myFuncLogPanic //记录panic日志,默认使用ZormErrorLog实现
	//zorm.FuncPrintSQL = myFuncPrintSQL //打印sql的函数

	//自定义日志输出格式,把FuncPrintSQL函数重新赋值
	//log.SetFlags(log.LstdFlags)
	//zorm.FuncPrintSQL = zorm.FuncPrintSQL

	//dbDaoConfig 数据库的配置.这里只是模拟,生产应该是读取配置配置文件,构造DataSourceConfig
	dbDaoConfig := zorm.DataSourceConfig{
		//DSN 数据库的连接字符串
		//DSN: "lawsuit:123456789@tcp(192.168.20.240:5236)/lawsuit?charset=utf8",
		//DSN: "root:root@tcp(127.0.0.1:3306)/readygo?charset=utf8&parseTime=true",
		DSN: "sa:@tcp(192.168.0.22:6000)/ecourt09?charset=cp936",
		//数据库驱动名称:mysql,postgres,oci8,sqlserver,sqlite3,dm,kingbase,aci 和DBType对应,处理数据库有多个驱动
		DriverName: "sybase",
		//数据库类型(方言判断依据):mysql,postgresql,oracle,mssql,sqlite,dm,kingbase,shentong 和 DriverName 对应,处理数据库有多个驱动
		DBType: "sybase",
		//MaxOpenConns 数据库最大连接数 默认50
		MaxOpenConns: 50,
		//MaxIdleConns 数据库最大空闲连接数 默认50
		MaxIdleConns: 50,
		//ConnMaxLifetimeSecond 连接存活秒时间. 默认600(10分钟)后连接被销毁重建.避免数据库主动断开连接,造成死连接.MySQL默认wait_timeout 28800秒(8小时)
		ConnMaxLifetimeSecond: 600,
		//PrintSQL 打印SQL.会使用FuncPrintSQL记录SQL
		PrintSQL: true,
		//DefaultTxOptions 事务隔离级别的默认配置,默认为nil
		//DefaultTxOptions: nil,
		//DefaultTxOptions: &sql.TxOptions{Isolation: sql.LevelDefault},
	}

	// 根据dbDaoConfig创建dbDao, 一个数据库只执行一次,第一个执行的数据库为 defaultDao,后续zorm.xxx方法,默认使用的就是defaultDao
	lawsuitDao, _ = zorm.NewDBDao(&dbDaoConfig)
}

func initMysqlDb() error {

	//自定义zorm日志输出
	//zorm.LogCallDepth = 4 //日志调用的层级
	//zorm.FuncLogError = myFuncLogError //记录异常日志的函数
	//zorm.FuncLogPanic = myFuncLogPanic //记录panic日志,默认使用ZormErrorLog实现
	//zorm.FuncPrintSQL = myFuncPrintSQL //打印sql的函数

	//自定义日志输出格式,把FuncPrintSQL函数重新赋值
	//log.SetFlags(log.LstdFlags)
	//zorm.FuncPrintSQL = zorm.FuncPrintSQL

	//dbDaoConfig 数据库的配置.这里只是模拟,生产应该是读取配置配置文件,构造DataSourceConfig
	dbDaoConfig := zorm.DataSourceConfig{
		//DSN 数据库的连接字符串
		//DSN: "lawsuit:123456789@tcp(192.168.20.240:5236)/lawsuit?charset=utf8",
		DSN: "root:@tcp(192.168.0.199:3306)/lawsuit?charset=utf8",
		//数据库驱动名称:mysql,postgres,oci8,sqlserver,sqlite3,dm,kingbase,aci 和DBType对应,处理数据库有多个驱动
		DriverName: "mysql",
		//数据库类型(方言判断依据):mysql,postgresql,oracle,mssql,sqlite,dm,kingbase,shentong 和 DriverName 对应,处理数据库有多个驱动
		DBType: "mysql",
		//MaxOpenConns 数据库最大连接数 默认50
		MaxOpenConns: 50,
		//MaxIdleConns 数据库最大空闲连接数 默认50
		MaxIdleConns: 50,
		//ConnMaxLifetimeSecond 连接存活秒时间. 默认600(10分钟)后连接被销毁重建.避免数据库主动断开连接,造成死连接.MySQL默认wait_timeout 28800秒(8小时)
		ConnMaxLifetimeSecond: 600,
		//PrintSQL 打印SQL.会使用FuncPrintSQL记录SQL
		PrintSQL: true,
		//DefaultTxOptions 事务隔离级别的默认配置,默认为nil
		//DefaultTxOptions: nil,
		//DefaultTxOptions: &sql.TxOptions{Isolation: sql.LevelDefault},
	}

	// 根据dbDaoConfig创建dbDao, 一个数据库只执行一次,第一个执行的数据库为 defaultDao,后续zorm.xxx方法,默认使用的就是defaultDao
	var err error
	lawsuitDao, err = zorm.NewDBDao(&dbDaoConfig)
	return err
}

const (
	//开发
	dev int = 1
	//测试
	tst int = 2

	wslaMysql int = 3
)

func createDb(dbType int) (db *sql.DB) {
	var ljc string
	var myDbType string = "mysql"
	switch dbType {
	case dev:
		ljc = "root:Tdh@123456@tcp(192.168.0.116:3306)/ssxf?charset=utf8"
	case tst:
		ljc = "root:tdhmaster@tcp(192.168.0.52:3306)/ssxf?charset=utf8"
	case wslaMysql:
		ljc = "root:@tcp(192.168.0.199:3306)/lawsuit?charset=utf8"
	}
	db, _ = sql.Open(myDbType, ljc)
	//设置数据库最大连接数
	db.SetConnMaxLifetime(100)
	//设置上数据库最大闲置连接数
	db.SetMaxIdleConns(10)
	//验证连接
	if err := db.Ping(); err != nil {
		fmt.Println("open database fail")
		return db
	}
	fmt.Println("connnect success")
	return db
}

func Rows2Maps(rows *sql.Rows) []map[string]interface{} {
	maps := make([]map[string]interface{}, 0)
	columns, _ := rows.Columns()
	for rows.Next() {
		m := make(map[string]interface{}, len(columns))
		vals := make([]interface{}, len(columns))
		for i, _ := range columns {
			var v interface{}
			vals[i] = &v
		}
		rows.Scan(vals...)
		for i, column := range columns {
			v := *vals[i].(*interface{})
			v = fmt.Sprintf("%s", v)
			m[column] = v
		}
		maps = append(maps, m)
	}
	rows.Close()
	return maps
}

var Dao *sqlx.DB
var TableSchema string
var Dsn string
var PageSize int

func init() {
	pwd, err := os.Getwd()
	if err != nil {
		fmt.Println("init pwd fail")
		return
	}
	config := pwd + "/db.properties"
	fmt.Println("config:", config)
	viper.SetConfigFile(config)
	err = viper.ReadInConfig()
	if err != nil {
		config = "C:/Users/DELL/go/src/super/db.properties"
		fmt.Println("init config fail,read default config,path=", config)
		viper.SetConfigFile(config)
		err = viper.ReadInConfig()
		if err != nil {
			fmt.Println("init fail")
			return
		}
	}
	TableSchema = viper.GetString("tableSchema")
	Dsn = viper.GetString("dsn")
	PageSize = viper.GetInt("pageSize")
}

func InitDB() (err error) {
	fmt.Printf("读取数据库tableSchema=%s,dsn=%s\n", TableSchema, Dsn)

	// 也可以使用MustConnect连接不成功就panic
	Dao, err = sqlx.Connect("mysql", Dsn)
	if err != nil {
		fmt.Printf("connect DB failed, err:%v\n", err)
		return
	}
	Dao.SetMaxOpenConns(2)
	Dao.SetMaxIdleConns(1)
	return
}
